<div class="doc-item" id="doc-1107"><h2 class="doc-item-name">parse-seq<span class="namespace">(clojure.contrib.lazy-xml)</span></h2><ul class="var-arglists"><li>(<span class="var-name">parse-seq</span>  s)</li><li>(<span class="var-name">parse-seq</span> s startparse)</li><li>(<span class="var-name">parse-seq</span> s startparse queue-size)</li></ul><div class="var-docstring"><p>Parses the source s, which can be a File, InputStream or String
  naming a URI. Returns a lazy sequence of maps with two or more of
  the keys :type, :name, :attrs, and :str. Other SAX-compatible
  parsers can be supplied by passing startparse, a fn taking a source
  and a ContentHandler and returning a parser. If a parser is
  specified, it will be run in a separate thread and be allowed to get
  ahead by queue-size items, which defaults to maxing.  If no parser
  is specified and org.xmlpull.v1.XmlPullParser is in the classpath,
  this superior pull parser will be used.</p></div><div class="var-source"><pre>; clojure/contrib/lazy_xml.clj:37
(defn parse-seq
  ([s] (if has-pull
         (parse-seq-pull s)
         (parse-seq s startparse-sax)))
  ([s startparse] (parse-seq s startparse Integer/MAX_VALUE))
  ([s startparse queue-size]
   (let [q (LinkedBlockingQueue. queue-size)
         NIL (Object.) ;nil sentinel since LBQ doesn't support nils
         agt (agent nil)
         s (if (instance? Reader s) (InputSource. s) s)
         step (fn step []
                (lazy-seq
                  (if-let [x (.take q)]
                    (cons x (step))
                    @agt)))  ;will be nil, touch agent just to propagate errors
         keep-alive (WeakReference. step)
         enqueue (fn [x]
                     (if (.get keep-alive)
                       (when-not (.offer q x 1 TimeUnit/SECONDS)
                                 (recur x))
                       (throw (Exception. &quot;abandoned&quot;))))]
     (send-off agt
       (fn [_]
         (try
           (startparse s (proxy [DefaultHandler] []
             (startElement [uri local-name q-name #^Attributes atts]
               ;(prn :start-element q-name)(flush)
               (let [attrs (into {} (for [i (range (.getLength atts))]
                                         [(keyword (.getQName atts i))
                                          (.getValue atts i)]))]
                 (enqueue (struct node :start-element (keyword q-name) attrs))))
             (endElement [uri local-name q-name]
               ;(prn :end-element q-name)(flush)
               (enqueue (struct node :end-element (keyword q-name))))
             (characters [ch start length]
               ;(prn :characters)(flush)
               (let [st (String. ch start length)]
                 (when (seq (.trim st))
                   (enqueue (struct node :characters nil nil st)))))))
           (finally
             (.put q false)))))
     (step))))</pre></div><div class="license"><p>Copyright (c) Rich Hickey. All rights reserved.</p><p>The use and distribution terms for this software are covered by the <a href="http://opensource.org/licenses/eclipse-1.0.php">Eclipse Public License 1.0</a>, which can be found in the file
          epl-v10.html at the root of this distribution. By using this software
          in any fashion, you are agreeing to be bound by the terms of this
          license. You must not remove this notice, or any other, from this
          software.</p></div></div>